// @(#)signal.cc
// Time-stamp: <2009-02-11 22:50:40 root>
// Copyright 2008 Julian Qian
// Author: lancer@pdn
// Version: $Id: signal.cc,v 0.0 2008/12/29 06:45:20 lancer Exp $
// Keywords: 

#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

#include <iostream>

#include "signal.hh"
#include "func.hh"
#include "excep.hh"
#include "alarm.hh"
#include "log.hh"
#include "inifile.hh"
#include "soap/wrapesms.hh"
#include "db.hh"
#include "heart.hh"



void set_pid(){
    pid_t pid;
    char* pidstr;
    FILE* fd;
    
	pid = getpid();
    pidstr = itoa((int)pid);
    
    if(fd = fopen(EHOME_PID, "w")){
        fwrite(pidstr, strlen(pidstr), 1, fd);
    }else{
        throw Exception("set_pid() failed!");
    }
    fclose(fd);
}

pid_t get_pid(){
    char buf[PID_LEN];
    FILE* fd;
    if(fd = fopen(EHOME_PID, "r")){
        fread(buf, PID_LEN, 1, fd);
    }
    fclose(fd);
    return (pid_t)atoi(buf);
}

void sig_setup(){
	struct sigaction act;	
	
	sigemptyset(&act.sa_mask);
	act.sa_sigaction = sig_action;
	act.sa_flags     = SA_SIGINFO;
	if(sigaction(EHOME_SIGNO, &act, NULL) < 0){
        // throw Exception("sig_setup() failed!");
        throw Exception(strerror(errno));
	}
	if(sigaction(SIGINT, &act, NULL) < 0){
        // throw Exception("sig_setup() failed!");
        throw Exception(strerror(errno));
	}
}

void sig_action(int signum, siginfo_t* info, void* act){
    // ALARM_PAIR* ap =  (ALARM_PAIR*)((*info).si_ptr);
    int sigtype = (*info).si_int;
    switch(sigtype){
    default:
        // quit server, keep this order.
        LInfo("Eh0m3 is shutting down...");
        Heart::endHeart();
        Alarm::endAlarm();
        // Db::endDb();
        Wrapesms::endWrapesms();
        Log::endLog();
        Config::endConfig();
        clean_memory_sgement();
        exit(0);
    }
}

void push_sig(pid_t pid, int sigtype){
	union sigval mysigval;
    
	// mysigval.sival_ptr = ap;
    mysigval.sival_int = sigtype;
    
    sigqueue(pid, EHOME_SIGNO, mysigval);
}

/*
void shm_alarm(){
	int shm_id;
	key_t shm_key;
	char *str_map;
	
	char shm_dev[] = SHM_DEVICE;
	if((shm_key = ftok(shm_dev, 't')) == -1){
		perror("ftok error!");
		return -1;
	}
	shm_id = shmget(shm_key, SHM_ESMS_SIZE, 0644 | IPC_CREAT);
	if(shm_id == -1){
		perror("shmget failed!");
		return -1;		
	}
	str_map = (char *)shmat(shm_id, NULL, 0);
	
	strncpy(str_map, pstr, SHM_ESMS_SIZE);

	if(shmdt(str_map) == -1){
		perror("detach failed!");
		return -1;		
	}
    
}

*/

void clean_memory_sgement(){
    using namespace boost::interprocess;

    try{
        managed_shared_memory segment (open_only , SHM_HEART_SEG );
        segment.destroy<HeartMap>(SHM_HEART_OBJ);
    }
    catch(const interprocess_exception &ex){
        std::cout << "distroy heartmap failed:" << ex.what() << std::endl;
    }
    shared_memory_object::remove(SHM_HEART_SEG);
    
    try{
        managed_shared_memory segment (open_only , SHM_MSG_SEG );
        segment.destroy<MsgList>(SHM_PUTMSG_OBJ);
    }
    catch(const interprocess_exception &ex){
        std::cout << "distroy msglist failed:" << ex.what() << std::endl;
    }
    shared_memory_object::remove(SHM_MSG_SEG);
}

